import { DeleteObjectCommand, GetObjectCommand, PutObjectAclCommand, PutObjectCommand, S3Client, } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

export type OSSConfig = {
  accessKeyId: string;
  accessKeySecret?: string;
  region?: string;
  bucket: string;
  endpoint: string;
  stsToken?: string;
}

class OSS {
  private client: S3Client;
  private bucket: string; // bucket name


  constructor({ bucket, endpoint, accessKeyId, accessKeySecret, region, stsToken, ...args }: OSSConfig) {
    this.bucket = bucket;
    const credentials: any = stsToken ? {
      accessKeyId: accessKeyId,
      secretAccessKey: accessKeySecret,
      sessionToken: stsToken, // 必须设置 SecurityToken
    } : {
      accessKeyId: accessKeyId,
      secretAccessKey: accessKeySecret,
    };
    // 默认使用https上传
    this.client = new S3Client({
      region: region || 's3',
      endpoint: endpoint?.startsWith('http') ? endpoint : `https://${endpoint}`,
      credentials: credentials,
      ...args
    });
  }

  /**
   * 获取签名地址
   * @param key 
   * @returns 
   */
  async signatureUrl(key: string, options?: any) {
    const getCommand = new GetObjectCommand({
      Bucket: this.bucket,
      Key: key,
    });
    return await getSignedUrl(this.client, getCommand, {...options});
  }

  // 上传文件
  async put(key: string, file: any) {
    const putCommand = new PutObjectCommand({
      Bucket: this.bucket,
      Key: key,
      Body: file,
    });
    await this.client.send(putCommand);
    // 获取签名地址
    const url = await this.signatureUrl(key);
    // 清除url中的search参数
    const urlObj = new URL(url);
    urlObj.search = '';
    return {
      url: urlObj.toString(),
    }
  }

  // 删除文件
  async del(key: string) {
    const deleteCommand = new DeleteObjectCommand({
      Bucket: this.bucket,
      Key: key,
    });
    await this.client.send(deleteCommand);
  }

  // 设置ACL
  async putACL(key: string, acl: any) {
    const putCommand = new PutObjectAclCommand({
      Bucket: this.bucket,
      Key: key,
      ACL: acl,
    });
    await this.client.send(putCommand);
  }

}
// 同时兼容CommonJS和ES Module
module.exports = OSS;
export default OSS;